#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/route.h>
#include <error.h>
#include <regex.h>

#define dmsg_tools_on 0
#if (dmsg_tools_on)
#define dmsg_tools(msg...)                                \
	do                                                    \
	{                                                     \
		printf("[tools] %04d, %s: ", __LINE__, __func__); \
		printf(msg);                                      \
	} while (0)
#else
#define dmsg_tools(msg...)
#endif

#define derr_tools_on 1
#if (derr_tools_on)
#define derr_tools(msg...)                                \
	do                                                    \
	{                                                     \
		printf("[tools] %04d, %s: ", __LINE__, __func__); \
		printf(msg);                                      \
	} while (0)
#else
#define derr_tools(msg...)
#endif

unsigned char utils_get_chartodata(char ch)
{
	switch (ch)
	{
	case '0':
		return 0;
	case '1':
		return 1;
	case '2':
		return 2;
	case '3':
		return 3;
	case '4':
		return 4;
	case '5':
		return 5;
	case '6':
		return 6;
	case '7':
		return 7;
	case '8':
		return 8;
	case '9':
		return 9;
	case 'a':
		return 10;
	case 'A':
		return 10;
	case 'b':
		return 11;
	case 'B':
		return 11;
	case 'c':
		return 12;
	case 'C':
		return 12;
	case 'd':
		return 13;
	case 'D':
		return 13;
	case 'e':
		return 14;
	case 'E':
		return 14;
	case 'f':
		return 15;
	case 'F':
		return 15;
	}
	return 0;
}

int utils_get_strtomac(char *macstr, unsigned char *macarray)
{
	int i = 0;
	char *pmacstr = macstr;
	for (i = 0; i < 6; ++i)
	{
		macarray[i] = utils_get_chartodata(*pmacstr) * 16;
		pmacstr++;
		macarray[i] += utils_get_chartodata(*pmacstr);
		pmacstr += 2;
	}
	return 0;
}

int utils_get_mactostr(unsigned char *macarray, char *macstr, char ckch)
{
	char fmtstr[] = "%02X.%02X.%02X.%02X.%02X.%02X";
	int len = strlen(fmtstr);
	int i = 0;
	if (ckch != '.')
	{
		for (i = 4; i < len; i += 5)
		{
			fmtstr[i] = ckch;
		}
	}
	sprintf(macstr, fmtstr, macarray[0], macarray[1], macarray[2], macarray[3], macarray[4], macarray[5]);
	return 0;
}

int utils_ckc_ipvalid(char *ipaddr)
{
	int dots = 0;	/*字符.的个数*/
	int setions = 0; /*ip每一部分总和（0-255）*/

	if (NULL == ipaddr || *ipaddr == '.')
	{
		return 1;
	}

	while (*ipaddr)
	{

		if (*ipaddr == '.')
		{
			dots++;
			if (setions >= 0 && setions <= 255)
			{ /*检查ip是否合法*/
				setions = 0;
				ipaddr++;
				continue;
			}
			return 1;
		}
		else if (*ipaddr >= '0' && *ipaddr <= '9')
		{											  /*判断是不是数字*/
			setions = setions * 10 + (*ipaddr - '0'); /*求每一段总和*/
		}
		else
		{
			return 1;
		}
		ipaddr++;
	}
	if (setions >= 0 && setions <= 255)
	{
		if (dots == 3)
		{
			return 0;
		}
	}
	return 1;
}

int utils_set_netinfo(char *ifname, char *ipaddr, char *netmask, char *gateway)
{
	int fd  = -1;
	int ret = 0;
	char syscmd[64];
	struct ifreq ifr;
	struct sockaddr_in *sin;
	struct rtentry rt;

	dmsg_tools("try set ipaddr : %s\n", ipaddr);
	dmsg_tools("try set netmask: %s\n", netmask);
	dmsg_tools("try set gateway: %s\n", gateway);

	system("ifconfig lo up");
	snprintf(syscmd, 64, "ifconfig %s down\n", ifname);
	system(syscmd);
	snprintf(syscmd, 64, "ifconfig %s up\n", ifname);
	system(syscmd);

	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (fd < 0)
	{
		derr_tools("get socket fd error\n");
		return -1;
	}
	memset(&ifr, 0, sizeof(ifr));
	strcpy(ifr.ifr_name, ifname);
	sin = (struct sockaddr_in *)&ifr.ifr_addr;
	sin->sin_family = AF_INET;

	//ipaddr
	if (inet_aton(ipaddr, &(sin->sin_addr)) < 0)
	{
		derr_tools("convert ipaddr failed!\n");
		close(fd);
		return -1;
	}

	if (ioctl(fd, SIOCSIFADDR, &ifr) < 0)
	{
		derr_tools("set ipaddr failed!\n");
		close(fd);
		return -1;
	}
	dmsg_tools("set ipaddr done!\n");

#if 1
	//netmask
	if (inet_aton(netmask, &(sin->sin_addr)) < 0)
	{
		derr_tools("convert netmask failed!\n");
		close(fd);
		return -1;
	}
	
	ret = ioctl(fd, SIOCSIFNETMASK, &ifr);
	if (ret < 0)
	{
		derr_tools("set netmask failed!, ret: %d\n", ret);
		close(fd);
		return -1;
	}
	dmsg_tools("set netmask done!\n");
#endif

	//gateway
	memset(&rt, 0, sizeof(struct rtentry));
	memset(sin, 0, sizeof(struct sockaddr_in));
	sin->sin_family = AF_INET;
	sin->sin_port = 0;
	if (inet_aton(gateway, &sin->sin_addr) < 0)
	{
		derr_tools("convert gateway failed!\n");
		close(fd);
		return -1;
	}
	memcpy(&rt.rt_gateway, sin, sizeof(struct sockaddr_in));
	((struct sockaddr_in *)&rt.rt_dst)->sin_family = AF_INET;
	((struct sockaddr_in *)&rt.rt_genmask)->sin_family = AF_INET;
	rt.rt_flags = RTF_GATEWAY;
	if (ioctl(fd, SIOCADDRT, &rt) < 0)
	{
		derr_tools("set gateway failed!\n");
		close(fd);
		return -1;
	}
	close(fd);
	dmsg_tools("set gateway done!\n");
	return 0;
}

int utils_set_macinfo(char *ifname, char *macaddr)
{
	unsigned char macarray[6];

	struct ifreq temp;
	struct sockaddr *addr;

	int fd = 0;
	int ret = -1;

	utils_get_strtomac(macaddr, macarray);

	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	{
		derr_tools("get socket fd error\n");
		return -1;
	}

	strcpy(temp.ifr_name, ifname);
	addr = (struct sockaddr *)&temp.ifr_hwaddr;

	addr->sa_family = ARPHRD_ETHER;
	memcpy(addr->sa_data, macarray, 6);

	ret = ioctl(fd, SIOCSIFHWADDR, &temp);
	close(fd);
	if (ret < 0)
	{
		derr_tools("set mac address failed\n");
		return -1;
	}
	return 0;
}

int utils_get_macinfo(char *ifname, char *macstr)
{
	unsigned char macarray[6];

	struct ifreq temp;
	struct sockaddr *addr;

	int fd = 0;
	int ret = -1;

	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	{
		derr_tools("get socket fd error\n");
		return -1;
	}

	strcpy(temp.ifr_name, ifname);
	addr = (struct sockaddr *)&temp.ifr_hwaddr;

	addr->sa_family = ARPHRD_ETHER;

	ret = ioctl(fd, SIOCGIFHWADDR, &temp);
	close(fd);

	if (ret < 0)
	{
		derr_tools("get mac address failed\n");
		return -1;
	}

	memcpy(macarray, addr->sa_data, 6);

	utils_get_mactostr(macarray, macstr, '.');

	return 0;
}

int utils_ckc_udhcpvalid(char *valstr)
{
	int err = 0;

	if((NULL == strstr(valstr, "on")) && (NULL == strstr(valstr, "off")))
	{
		return 1;
	}
	return 0;
}

int utils_ckc_portvalid(char *valstr)
{
	int val = atoi(valstr);
	if (val < 1 || val > 65535)
	{
		return 1;
	}
	return 0;
}

int utils_ckc_macvalid(char *mac)
{

	int status;
	const char *pattern = "^([A-Fa-f0-9]{2}[-,.]){5}[A-Fa-f0-9]{2}$";
	const int cflags = REG_EXTENDED | REG_NEWLINE;

	char ebuf[128];
	regmatch_t pmatch[1];
	int nmatch = 10;
	regex_t reg;

	status = regcomp(&reg, pattern, cflags); //编译正则模式
	if (status != 0)
	{
		regerror(status, &reg, ebuf, sizeof(ebuf));
		derr_tools("regcomp fail: %s , pattern '%s' \n", ebuf, pattern);
		goto failed;
	}

	status = regexec(&reg, mac, nmatch, pmatch, 0); //执行正则表达式和缓存的比较,
	if (status != 0)
	{
		regerror(status, &reg, ebuf, sizeof(ebuf));
		derr_tools("regexec fail: %s , mac:\"%s\" \n", ebuf, mac);
		goto failed;
	}
	return 0;
failed:
	return 1;
}

int utils_ckc_pspidvalid(char *valstr)
{
#if 0
	int val = atoi(valstr);
	if (val < 1 || val > 65535)
	{
		return 1;
	}
#endif
	return 0;
}

int utils_ltrim(char *s)
{
    int i=0, j=0;
    //传入空值则退出
    if(!strlen(s)) return;
    //找到首个不为空的字符
    while( s[i] == ' '&& s[i] != '\0') i++;
    //从i位置的字符开始左移i个位置
    while( s[i] != '\0') s[j++] = s[i++];
    s[j] = '\0';
}
 
int utils_rtrim(char *s)
{
    int pos;
    pos = strlen(s) - 1;
    //若尾部字符为空，则将其设置为末尾字符
    while( s[pos] == ' ' ) {
        s[pos--] = '\0';
        if(pos<0) break;
    }
}
 
// 去除左右的空格
int utils_trim(char *s)
{
	utils_ltrim(s);
	utils_rtrim(s);
}
